// 云函数入口文件
const cloud = require('wx-server-sdk')
const OpenAI = require('openai')

// 初始化云开发环境
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

const db = cloud.database()

// 检查必要的环境变量
function checkEnvironmentVariables() {
  const apiKey = process.env.DASHSCOPE_API_KEY;
  if (!apiKey) {
    throw new Error('未配置 DASHSCOPE_API_KEY 环境变量，请在云开发控制台添加环境变量');
  }
  return apiKey;
}

// 云函数入口函数
exports.main = async (event, context) => {
  try {
    // 检查环境变量
    console.log("开始执行云函数，操作类型:", event.action);
    
    // 显式获取并检查API密钥
    const apiKey = process.env.DASHSCOPE_API_KEY;
    console.log("API密钥是否存在:", apiKey ? "存在" : "不存在");
    if (!apiKey) {
      throw new Error('未配置 DASHSCOPE_API_KEY 环境变量，请在云开发控制台添加环境变量');
    }

    const wxContext = cloud.getWXContext()
    const { action } = event

    // 根据操作类型执行不同逻辑
    console.log("执行操作:", action);
    
    switch (action) {
      case 'generateRecipe':
        return await generateAndSaveRecipe(wxContext);
      case 'regenerateRecipe':
        // 重新生成会清除缓存
        console.log("清除旧缓存并重新生成");
        await clearRecipeCache(wxContext.OPENID);
        return await generateAndSaveRecipe(wxContext);
      case 'getRecipe':
        return await getLatestRecipe(wxContext);
      case 'clearCache':
        return await clearRecipeCache(wxContext.OPENID);
      case 'testApi':
        console.log("执行API连接测试");
        return await testApiConnection();
      default:
        console.error("未知的操作类型:", action);
        return {
          success: false,
          message: `未知的操作类型: ${action}`
        };
    }
  } catch (error) {
    console.error('云函数执行失败:', error.message, error.stack);
    return {
      success: false,
      message: error.message || '服务器内部错误',
      error: {
        code: error.code || -1,
        details: error.details || null
      }
    };
  }
}

// 检查缓存
async function checkRecipeCache(openid) {
  try {
    const currentTime = new Date()
    const cacheKey = `recipe_${openid}`
    
    const cacheResult = await db.collection('recipes_cache')
      .where({
        cache_key: cacheKey,
        expire_time: db.command.gt(currentTime)
      })
      .limit(1)
      .get()
    
    if (cacheResult.data && cacheResult.data.length > 0) {
      console.log('找到有效缓存')
      return cacheResult.data[0].data
    }
    
    console.log('未找到有效缓存')
    return null
  } catch (error) {
    console.error('检查缓存出错:', error)
    return null
  }
}

// 保存缓存
async function saveToCache(openid, data) {
  try {
    const cacheKey = `recipe_${openid}`
    const currentTime = new Date()
    const expireTime = new Date(currentTime.getTime() + 24 * 60 * 60 * 1000) // 24小时后过期
    
    // 先检查是否已有缓存
    const existCache = await db.collection('recipes_cache')
      .where({
        cache_key: cacheKey
      })
      .get()
    
    // 如果已有缓存，则更新
    if (existCache.data && existCache.data.length > 0) {
      await db.collection('recipes_cache').doc(existCache.data[0]._id).update({
        data: {
          data: data,
          expire_time: expireTime,
          update_time: currentTime
        }
      })
    } else {
      // 否则创建新缓存
      await db.collection('recipes_cache').add({
        data: {
          cache_key: cacheKey,
          data: data,
          expire_time: expireTime,
          create_time: currentTime
        }
      })
    }
    
    console.log('缓存保存成功')
    return true
  } catch (error) {
    console.error('保存缓存出错:', error)
    return false
  }
}

// 清除缓存
async function clearRecipeCache(openid) {
  try {
    const cacheKey = `recipe_${openid}`
    
    const result = await db.collection('recipes_cache')
      .where({
        cache_key: cacheKey
      })
      .remove()
    
    console.log('缓存清除结果:', result)
    return {
      success: true,
      message: '缓存已清除'
    }
  } catch (error) {
    console.error('清除缓存出错:', error)
    return {
      success: false,
      message: '清除缓存失败'
    }
  }
}

// 生成并保存食谱
async function generateAndSaveRecipe(wxContext) {
  try {
    console.log('开始生成食谱')
    
    // 获取用户家庭信息
    const familyResult = await db.collection('familyMembers')
      .where({
        _openid: wxContext.OPENID
      })
      .get()
    
    if (!familyResult.data || familyResult.data.length === 0) {
      return {
        success: false,
        message: '请先添加家庭成员信息'
      }
    }
    
    // 获取食材信息
    const foodItemsResult = await db.collection('foodItems')
      .where({
        _openid: wxContext.OPENID
      })
      .get()
    
    // 检查是否已有缓存的食谱
    const cachedRecipe = await checkRecipeCache(wxContext.OPENID)
    if (cachedRecipe) {
      return {
        success: true,
        recipe: cachedRecipe,
        message: '成功获取食谱',
        cached: true
      }
    }
    
    // 构建提示词
    const prompt = buildRecipePrompt(
      familyResult.data, 
      foodItemsResult.data || []
    )
    
    // 调用AI生成食谱
    console.log('开始调用AI生成食谱')
    const aiResult = await generateRecipeWithAI(JSON.stringify(prompt))
    console.log('AI生成结果:', JSON.stringify(aiResult))
    
    // 解析并格式化AI返回的结果
    const formattedRecipe = parseRecipeResult(aiResult)
    
    // 保存到数据库
    const saveResult = await saveRecipeToDatabase(formattedRecipe, wxContext.OPENID)
    
    return {
      success: true,
      recipe: formattedRecipe,
      message: '食谱生成成功',
      recipeId: saveResult._id
    }
  } catch (error) {
    console.error('生成食谱失败:', error)
    return {
      success: false,
      message: error.message || '食谱生成失败，请稍后重试'
    }
  }
}

// 构建食谱生成提示词
function buildRecipePrompt(familyMembers, foodItems) {
  // 构建家庭成员信息
  const members = familyMembers.map(member => ({
    角色: member.name,
    年龄: parseInt(member.age),
    身高: parseInt(member.height),
    体重: parseInt(member.weight),
    偏好: member.favor || '无',
    忌口: member.avoid || '无'
  }))

  // 计算每个成员的BMI和能量需求
  const membersWithNutrition = members.map(member => {
    const heightInMeter = member.身高 / 100;
    const bmi = member.体重 / (heightInMeter * heightInMeter);
    let bodyType = '正常';
    if (bmi < 18.5) bodyType = '偏瘦';
    else if (bmi >= 25) bodyType = '偏胖';
    
    // 根据体型和年龄估算每公斤能量需求
    let energyPerKg = 35; // 默认值
    if (member.年龄 < 18) energyPerKg = 40;
    else if (member.年龄 > 60) energyPerKg = 30;
    
    // 调整体型因素
    if (bodyType === '偏瘦') energyPerKg += 5;
    else if (bodyType === '偏胖') energyPerKg -= 5;
    
    // 计算总能量需求
    const totalEnergy = Math.round(energyPerKg * member.体重);
    
    return {
      ...member,
      BMI: bmi.toFixed(1),
      体型: bodyType,
      每日能量需求: totalEnergy,
      早餐能量: Math.round(totalEnergy * 0.3),
      午餐能量: Math.round(totalEnergy * 0.4),
      晚餐能量: Math.round(totalEnergy * 0.3)
    };
  });

  // 构建简化的提示词
  const prompt = {
    需求: `为${familyMembers.length}口之家生成未来一周（周一至周日）的早午晚餐食谱`,
    家庭成员: membersWithNutrition,
    健康指南: {
      能量分配: '早餐占30%，午餐占40%，晚餐占30%',
      营养均衡: '每餐应包含主食、肉蛋奶、蔬菜水果等多种食物类别',
      注意事项: '考虑家庭成员的年龄、体型和饮食偏好，确保营养均衡'
    },
    输出要求: {
      格式: 'JSON',
      内容: '仅需提供每日三餐的菜名，不需要详细的食材和烹饪步骤',
      结构示例: {
        '周一': {
          '早餐': ['牛奶麦片', '水煮蛋', '黄瓜'],
          '午餐': ['米饭', '清蒸鱼', '炒青菜'],
          '晚餐': ['全麦面包', '蔬菜沙拉', '鸡胸肉']
        }
      }
    }
  }

  console.log('生成的提示词:', JSON.stringify(prompt, null, 2));
  return prompt;
}

// 调用AI生成食谱
async function generateRecipeWithAI(prompt) {
  try {
    console.log('===== AI生成食谱开始 =====');
    
    // 检查API密钥
    const apiKey = process.env.DASHSCOPE_API_KEY;
    if (!apiKey) {
      console.error('API密钥未配置，无法调用通义千问API');
      throw new Error('API密钥未配置');
    }
    
    console.log('API密钥长度:', apiKey.length);
    console.log('API密钥前4位:', apiKey.substring(0, 4));
    
    console.log('开始请求通义千问API生成食谱');
    
    // 为了调试，先返回默认数据，不调用API
    if (process.env.DEBUG_MODE === 'true') {
      console.log('调试模式：返回默认食谱数据');
      return createFallbackResponse();
    }
    
    // 创建OpenAI客户端实例（使用通义千问的API地址）
    try {
      console.log('正在创建OpenAI客户端...');
      const openai = new OpenAI({
        apiKey: apiKey,
        baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1', // 通义千问兼容模式的API地址
      });
      
      console.log('OpenAI客户端创建成功');
      
      // 检查是否为对象，如果是则转为JSON字符串
      const promptText = typeof prompt === 'object' ? 
        JSON.stringify(prompt, null, 2) : prompt;
      
      console.log('发送到API的提示词类型:', typeof promptText);
      console.log('提示词长度:', promptText.length);
      
      // 使用更简化的系统提示
      const systemPrompt = '你是一个专业的营养师，为家庭成员生成一周三餐的食谱菜名。严格按JSON格式输出，每天三餐的菜名列表。';
      console.log('系统提示:', systemPrompt);
      
      // 构建请求参数
      const requestParams = {
        model: 'qwen-plus', // 确保模型名称正确：通义千问-Plus
        messages: [
          {
            role: 'system',
            content: systemPrompt
          },
          {
            role: 'user',
            content: promptText
          }
        ],
        temperature: 0.7,
        top_p: 0.8,
        max_tokens: 2000,
        response_format: { type: 'json_object' }
      };
      
      console.log('API请求参数:', JSON.stringify(requestParams));
      console.log('正在发送API请求...');
      
      const response = await openai.chat.completions.create(requestParams);
      
      console.log('API请求成功，响应状态:', response.model);
      if (response.usage) {
        console.log('API耗费Token:', JSON.stringify(response.usage));
      }
      
      // 检查API响应格式
      if (!response?.choices?.[0]?.message?.content) {
        console.error('API返回结果格式不正确:', JSON.stringify(response));
        throw new Error('API返回结果格式不正确');
      }
      
      const content = response.choices[0].message.content;
      console.log('API返回内容前100字符:', content.substring(0, 100) + '...');
      
      // 尝试解析JSON
      let jsonContent;
      try {
        jsonContent = JSON.parse(content);
        console.log('成功解析JSON数据');
        console.log('JSON数据键:', Object.keys(jsonContent));
      } catch (error) {
        console.error('JSON解析失败:', error.message);
        console.log('尝试从文本中提取JSON部分');
        
        // 尝试从文本中提取JSON
        console.log('尝试提取JSON格式...');
        const jsonMatch = content.match(/```json\s*([\s\S]*?)\s*```/) || 
                        content.match(/{[\s\S]*}/s);
        
        if (jsonMatch) {
          const jsonText = jsonMatch[1] || jsonMatch[0];
          console.log('找到可能的JSON文本，尝试解析...');
          try {
            jsonContent = JSON.parse(jsonText);
            console.log('从文本中提取并解析JSON成功');
          } catch (e) {
            console.error('提取的JSON解析失败:', e.message);
            console.log('返回默认食谱数据');
            jsonContent = createFallbackResponse();
          }
        } else {
          console.error('无法从返回内容中提取JSON');
          jsonContent = createFallbackResponse();
        }
      }
      
      console.log('===== AI生成食谱完成 =====');
      return jsonContent;
    } catch (error) {
      console.error('OpenAI客户端创建或调用失败:', error.message, error.stack);
      throw error;
    }
  } catch (error) {
    console.error('调用AI生成食谱失败:', error.message, error.stack);
    console.log('返回默认食谱数据');
    return createFallbackResponse();
  }
}

// 创建一个基本的食谱结构，用于API调用失败时返回
function createFallbackResponse() {
  console.log('创建默认食谱数据');
  const weekDays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
  const fallback = {};
  
  // 默认食谱数据
  const defaultMeals = {
    '周一': {
      '早餐': ['牛奶麦片', '水煮蛋', '全麦面包'],
      '午餐': ['米饭', '清蒸鲈鱼', '炒青菜', '紫菜汤'],
      '晚餐': ['意面', '番茄牛肉', '凉拌黄瓜']
    },
    '周二': {
      '早餐': ['豆浆', '油条', '小米粥'],
      '午餐': ['五谷杂粮饭', '红烧肉', '蒜蓉西兰花'],
      '晚餐': ['燕麦粥', '清蒸鸡胸肉', '凉拌海带']
    },
    '周三': {
      '早餐': ['牛奶', '鸡蛋饼', '水果沙拉'],
      '午餐': ['米饭', '鱼香肉丝', '酸辣汤'],
      '晚餐': ['藜麦饭', '香煎三文鱼', '西红柿沙拉']
    },
    '周四': {
      '早餐': ['黑米粥', '煎饺', '豆浆'],
      '午餐': ['烩面', '红烧排骨', '清炒油菜'],
      '晚餐': ['糙米饭', '清蒸豆腐', '鸡蛋汤']
    },
    '周五': {
      '早餐': ['燕麦片', '牛奶', '煮鸡蛋'],
      '午餐': ['米饭', '红烧带鱼', '炝炒圆白菜'],
      '晚餐': ['薏米粥', '西兰花虾仁', '黄瓜沙拉']
    },
    '周六': {
      '早餐': ['三明治', '牛奶', '香蕉'],
      '午餐': ['米饭', '可乐鸡翅', '紫菜蛋花汤'],
      '晚餐': ['意大利面', '烤鸡胸', '蔬菜沙拉']
    },
    '周日': {
      '早餐': ['皮蛋瘦肉粥', '油条', '豆浆'],
      '午餐': ['米饭', '宫保鸡丁', '酸辣土豆丝'],
      '晚餐': ['藜麦饭', '清蒸鱼', '番茄蛋汤']
    }
  };
  
  weekDays.forEach(day => {
    fallback[day] = defaultMeals[day];
  });
  
  console.log('默认食谱数据创建完成');
  return fallback;
}

// 解析AI返回的JSON结果
function parseRecipeResult(result) {
  const weekDays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
  const mealTypes = ['早餐', '午餐', '晚餐'];

  console.log('开始解析AI返回的JSON结果，数据类型:', typeof result);
  if (Array.isArray(result)) {
    console.log('结果是数组，长度:', result.length);
  } else if (typeof result === 'object') {
    console.log('结果是对象，键:', Object.keys(result));
  }
  
  try {
    // 如果result已经是数组格式，直接返回
    if (Array.isArray(result) && result.length > 0 && result[0].day && result[0].meals) {
      console.log('返回结果已经是标准格式数组');
      return result;
    }
    
    // 转换为标准格式
    return weekDays.map(day => {
      // 检查day是否存在于result中
      const dayData = result[day] || {};
      
      return {
        day,
        meals: mealTypes.map(type => {
          // 获取餐点数据
          let mealContent = dayData[type];
          
          // 如果餐点数据是数组，则转换为字符串
          if (Array.isArray(mealContent)) {
            mealContent = mealContent.join('、');
            console.log(`${day} ${type} 数据是数组，转换为:`, mealContent);
          } 
          // 如果餐点数据是对象，则提取菜名
          else if (typeof mealContent === 'object' && mealContent !== null) {
            if (Array.isArray(mealContent.菜名)) {
              mealContent = mealContent.菜名.join('、');
              console.log(`${day} ${type} 数据是带菜名的对象，提取菜名:`, mealContent);
            } else {
              mealContent = JSON.stringify(mealContent);
              console.log(`${day} ${type} 数据是复杂对象，转为字符串`);
            }
          }
          // 如果没有数据，则提供默认值
          else if (!mealContent) {
            mealContent = type === '早餐' ? '牛奶、鸡蛋、全麦面包' : 
                          type === '午餐' ? '米饭、炒青菜、红烧肉' : 
                                         '米饭、清蒸鱼、凉拌黄瓜';
            console.log(`${day} ${type} 数据为空，使用默认值:`, mealContent);
          }
          
          return {
            type,
            content: typeof mealContent === 'string' ? mealContent : JSON.stringify(mealContent)
          };
        })
      };
    });
  } catch (error) {
    console.error('解析AI返回结果出错:', error.message, error.stack);
    
    // 返回一个基本的食谱结构
    return weekDays.map(day => ({
      day,
      meals: mealTypes.map(type => ({
        type,
        content: type === '早餐' ? '牛奶、鸡蛋、全麦面包' : 
                type === '午餐' ? '米饭、炒青菜、红烧肉' : 
                               '米饭、清蒸鱼、凉拌黄瓜'
      }))
    }));
  }
}

// 格式化餐食内容
function formatMealContent(meal) {
  if (typeof meal === 'string') {
    return meal
  }
  
  const parts = []
  if (meal.菜名) parts.push(meal.菜名)
  if (meal.食材清单) {
    const ingredients = Array.isArray(meal.食材清单) 
      ? meal.食材清单.join('、') 
      : typeof meal.食材清单 === 'string' ? meal.食材清单 : JSON.stringify(meal.食材清单);
    parts.push(`食材：${ingredients}`);
  }
  if (meal.烹饪步骤) {
    const steps = Array.isArray(meal.烹饪步骤) 
      ? meal.烹饪步骤.join('\n') 
      : meal.烹饪步骤;
    parts.push(`烹饪步骤：${steps}`);
  }
  if (meal.热量) parts.push(`热量：${meal.热量}`);
  if (meal.适合人群) parts.push(`适合：${meal.适合人群}`);
  if (meal.准备时间) parts.push(`准备时间：${meal.准备时间}`);
  
  return parts.join('\n')
}

// 解析AI返回的文本（当JSON解析失败时使用）
function parseRecipeText(text) {
  const weekDays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  const mealTypes = ['早餐', '午餐', '晚餐']
  
  // 简单的文本解析逻辑
  const recipes = weekDays.map(day => {
    const dayPattern = new RegExp(`${day}[：:](.*?)(?=${weekDays.slice(1).join('|')}|$)`, 's')
    const dayMatch = text.match(dayPattern)
    const dayContent = dayMatch ? dayMatch[1].trim() : ''
    
    const meals = mealTypes.map(type => {
      const mealPattern = new RegExp(`${type}[：:](.*?)(?=${mealTypes.slice(1).join('|')}|$)`, 's')
      const mealMatch = dayContent.match(mealPattern)
      return {
        type,
        content: mealMatch ? mealMatch[1].trim() : `${type}菜单生成中`
      }
    })
    
    return {
      day,
      meals
    }
  })
  
  return recipes
}

// 获取最新食谱
async function getLatestRecipe(wxContext) {
  try {
    const recipe = await db.collection('recipes')
      .where({
        _openid: wxContext.OPENID,
        status: 'active'
      })
      .orderBy('createTime', 'desc')
      .limit(1)
      .get()
      .then(res => res.data[0])

    if (!recipe) {
      return {
        success: false,
        message: '未找到食谱'
      }
    }

    return {
      success: true,
      data: recipe
    }
  } catch (error) {
    console.error('获取食谱失败', error)
    return {
      success: false,
      message: error.message || '获取食谱失败'
    }
  }
}

// 将食谱保存到数据库
async function saveRecipeToDatabase(formattedRecipe, openid) {
  const recipeData = {
    weeklyRecipes: formattedRecipe,
    createTime: new Date(),
    _openid: openid,
    status: 'active'
  }

  // 保存到数据库
  const result = await db.collection('recipes').add({
    data: recipeData
  })
  
  // 同时保存到缓存
  await saveToCache(openid, {...recipeData, _id: result._id})
  
  return { _id: result._id }
}

// 测试API连接
async function testApiConnection() {
  try {
    console.log('开始测试API连接');
    
    // 获取API密钥
    const apiKey = process.env.DASHSCOPE_API_KEY;
    if (!apiKey) {
      console.error('API密钥未配置，无法进行API测试');
      return {
        success: false,
        message: 'API密钥未配置'
      };
    }
    
    console.log('API密钥长度:', apiKey.length);
    console.log('API密钥前4位:', apiKey.substring(0, 4));
    
    try {
      // 创建简单的OpenAI客户端
      console.log('正在创建OpenAI客户端...');
      const openai = new OpenAI({
        apiKey: apiKey,
        baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
      });
      
      console.log('OpenAI客户端创建成功');
      
      // 发送简单的测试请求
      console.log('正在发送测试请求...');
      const response = await openai.chat.completions.create({
        model: 'qwen-plus',
        messages: [
          {
            role: 'system',
            content: '你是一个简单的测试助手'
          },
          {
            role: 'user',
            content: '请回复"API连接测试成功"'
          }
        ],
        max_tokens: 20
      });
      
      console.log('API请求成功，响应:', JSON.stringify(response));
      
      // 检查响应
      if (response && response.choices && response.choices[0] && response.choices[0].message) {
        console.log('测试成功，返回内容:', response.choices[0].message.content);
        return {
          success: true,
          message: '测试成功',
          response: {
            content: response.choices[0].message.content,
            model: response.model,
            tokens: response.usage
          }
        };
      } else {
        console.error('API返回结果格式不正确:', JSON.stringify(response));
        return {
          success: false,
          message: '无法获取有效响应',
          response: response
        };
      }
    } catch (error) {
      console.error('API客户端创建或调用失败:', error.message, error.stack);
      return {
        success: false,
        message: error.message || 'API客户端创建或调用失败',
        error: error.toString()
      };
    }
  } catch (error) {
    console.error('API连接测试失败:', error.message, error.stack);
    return {
      success: false,
      message: error.message || 'API连接测试失败',
      error: error.toString()
    };
  }
} 